package cn.tedu.charging.order.mqtt;

import cn.tedu.charging.common.pojo.utils.JsonUtils;
import cn.tedu.charging.order.common.ChargingConstants;
import cn.tedu.charging.order.common.MqttConstants;
import cn.tedu.charging.order.common.OrderStatusConstants;
import cn.tedu.charging.order.pojo.dto.ChargingResultDto;
import cn.tedu.charging.order.pojo.po.ChargingOrderFailPO;
import cn.tedu.charging.order.pojo.po.ChargingOrderSuccessPO;
import com.alibaba.nacos.shaded.org.checkerframework.checker.units.qual.A;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 消费者
 * MqttConsumer没在容器里面   而mqttClient在容器里面
 * 要求是没在容器里面的类MqttConsumer 要使用容器里面的mqttClient
 */
@Slf4j
public class MqttConsumer implements MqttCallbackExtended {
//    @Autowired
//    private MqttClient mqttClient;
private MqttClient mqttClient;

private MqttContext mqttContext;

    /**
     * 没有在容器中的 MqttConsumer 想使用 容器中 MqttClient
     * 可以在创建 MqttConsumer 的时候，把 MqttClient 通过构造方法 传入进来
     * @param mqttClient
     */
    public MqttConsumer(MqttClient mqttClient,MqttContext mqttContext){

        this.mqttClient = mqttClient;
        this.mqttContext = mqttContext;
}

    /**
     * 通过setter方法 设置MqttClient
     */
public void setMqttClient(MqttClient mqttClient){
    this.mqttClient = mqttClient;
}

    @Override
    public void connectComplete(boolean reconnect, String serverURI) {
        log.debug("connectComplete连接成功:reconnect:{},serverURI:{}",
                reconnect,serverURI);
//在和EMQX连接成功后 订阅Topic
        //设备返回的开始充电结果Topic
        String topicChargingResult = MqttConstants.TOPIC_CHARGING_RESULT;

        try {
            log.debug("订单服务订阅设备返回的开始充电结果Topic:{}",topicChargingResult);
            //通过subscribe来订阅
            mqttClient.subscribe(topicChargingResult);
        } catch (MqttException e) {
            //打印异常信息 可能进行重试，如果还是连接不上，要接入告警系统 告警（给运维开发告警了）
            throw new RuntimeException(e);
        }
        log.debug("订单服务订阅设备返回的开始充电结果Topic:{},成功",topicChargingResult);

    }
    //你丢失了，告诉我一个丢失的原因
    @Override
    public void connectionLost(Throwable cause) {

    log.debug("connectionLost 连接丢失:{}",cause);
    //在连接丢失的时候，可以通过mqttClient 重连
    //mqttClient.connect();
    }
    //从哪到哪也不知道 String topic是收的 具体的消息指的是什么MqttMessage message

    /**
     * 消息到达
     * 设备  给  订单服务 发送的消息 到达了
     *
     */
    @Override //message是一个对象 这是个消息，消息是个字符串
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        log.debug("messageArrived 收到设备发送的消息:topic:{},message:{}",
                topic,message);
        //new String(payload); //字节数组转换为字符串  payload就是字节数组


        //这时候需要message对象要转换成字符串 ， 把字符串转换为对象
        ChargingResultDto chargingResultDto =null;
//        try {
            chargingResultDto = JsonUtils.fromJson(message.toString(),
                  ChargingResultDto.class);
//        } catch (Exception e) {
//            //如果多次失败，应该告警
//            log.debug("解析设备返回的消息失败:{}",e);
//        }
        //获取设备返回开始充电的结果
        log.debug("收到设备返回的开始充电的结果:{}",chargingResultDto);
        if(chargingResultDto !=null){

            String result = chargingResultDto.getResult();
            if(ChargingConstants.CHARGING_RESULT_SUCCESS.equals(result)){
                log.debug("设备发送的消息是 开始充电成功的消息");
                ChargingOrderSuccessPO successPO = new ChargingOrderSuccessPO();
                successPO.setBillId( chargingResultDto.getOrderNo());
                successPO.setGunId(chargingResultDto.getGunId());
                //订单服务收到设备 开始充电成功 消息 保存成功订单记录 订单的状态 充电中
                successPO.setBillStatus(OrderStatusConstants.ORDER_STATUS_CHARGING);
                log.debug("保存成功订单记录:{}",successPO);
                int row = mqttContext.getOrderSuccessMapper().insert(successPO);
                log.debug("保存成功订单记录：:{},影响行数:{}",successPO,row);

                //todo 保存成功订单记录  设备要同步充电进度了 5度 10度 15度 最后一跳闸说充满了
                //todo 设备会定时的和订单服务同步充电进度数据 直到车辆电池充满
            }else{
                log.debug("设备发送的消息是 开始充电失败的消息");
                ChargingOrderFailPO chargingOrderFailPO = new ChargingOrderFailPO();
                chargingOrderFailPO.setBillId(chargingResultDto.getOrderNo());
                chargingOrderFailPO.setFailDesc("设备有响应，开始充电失败");
                log.debug("保存失败订单记录:{}",chargingOrderFailPO);
                int row = mqttContext.getOrderFailMapper().insert(chargingOrderFailPO);
                log.debug("保存失败订单记录:{},影响行数:{}",chargingOrderFailPO,row);
                //todo  保存失败订单记录
                //todo
                log.debug("设备发送的消息是 开始充电失败，<<通知用户>> 提醒用户请更换设备");
                log.debug("给用户发送优惠券,表示歉意,给予心灵上的告慰");
                log.debug("修改枪的状态为 <<故障>>");
                log.debug("通知设备管理员 进行设备的检修");

            }
        }
    }
    //谁给谁发的完成也不知道
    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        log.debug("deliveryComplete 消息发送完成:{}",token);
    }
}
